﻿using GN.Pay.TradeChannel;
using System;
using System.Collections.Generic;
using GN.Pay.TradeChannel.DefaultImpl;
using GN.Pay.Utils;
using System.Xml;
using System.Xml.Linq;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using GN.Pay.TradeChannel.WeiXin.Response;
using GN.Pay.TradeChannel.WeiXin.Request;
using GN.Pay.TradeChannel.Configure;
using GN.Pay.TradeChannel.Transfers;

namespace GN.Pay.TradeChannel.WeiXin
{
    [Serializable]
    public abstract class WeiXinServiceBase : ATradeChannel<string>, ITransfers
    {
        public readonly WeiXinConfigure channelConfigure;
        public WeiXinServiceBase()
        {
            ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
            this.channelConfigure = new WeiXinConfigure(this);
        }

        public sealed override ITradeChannelConfigure ChannelConfigure
        {
            get
            {
                return this.channelConfigure;
            }
        }

        /// <summary>
        /// 获取提供者全称
        /// </summary>
        public sealed override string ChannelProvider
        {
            get
            {
                return "深圳市财付通科技有限公司";
            }
        }

        public override Type TradeChannelConfigureInfoType
        {
            get
            {
                return typeof(WeiXinConfigureInfo);
            }
        }
        /// <summary>
        /// 交易类型
        /// </summary>
        public abstract string TradeType { get; }

        private static IChannel TempChannel = TradeChannelInfo.Create("WeiXin", "微信");


        /// <summary>
        /// 获取付款的订单号
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        public static string GetPayOrderNo(string message)
        {
            if (string.IsNullOrWhiteSpace(message))
            {
                return null;
            }
            PayNotifyResponse res = new PayNotifyResponse(message);
            if (!res.IsReturnSuccess())
            {
                return null;
            }
            return res.Out_Trade_No;
        }


        /// <summary>
        /// 获取退款批次号
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        public static string GetRefundNo(string message)
        {
            return null;
        }

        public override void OrderPayNotify(INotifyService sercice, string message)
        {
            if (string.IsNullOrWhiteSpace(message))
            {
                throw new ArgumentNullException(nameof(message));
            }
            PayNotifyResponse res = new PayNotifyResponse(message);
            if (!res.IsReturnSuccess())
            {
                this.ThrowInterfaceException(res.Return_Msg);
            }
            if (!res.IsResultSuccess())
            {
                if (string.IsNullOrWhiteSpace(res.Err_Code_Des))
                {
                    this.ThrowInterfaceException(res.Err_Code);
                }
                this.ThrowInterfaceException(res.Err_Code_Des);
            }
            if (!res.SignVerify(channelConfigure))
            {
                this.ThrowChannelValidationException("微信支付通知验签失败");
            }
            var refundResult = res.ToPayResult(this);
            sercice.OrderPayNotify(refundResult);
        }

        public override void OrderRefundNotify(INotifyService sercice, string message)
        {
            throw new NotImplementedException("微信不支持退款通知");
        }

        //TODO:查询
        public override ITradeOrderQueryResult OrderSingleQuery(DateTime queryDate, string orderNo, string tradeNo)
        {
            if (string.IsNullOrWhiteSpace(orderNo) && string.IsNullOrWhiteSpace(tradeNo))
            {
                TradeChannelExceptionUtils.ThrowClientRequestException(this.ChannelId, "查询订单时，交易号或者订单号必须提供一项。");
            }
            var config = this.channelConfigure;
            var request = new QueryRequest(this, config, tradeNo, orderNo);
            var response = request.Build();
            if (!response.SignVerify(config))
            {
                TradeChannelExceptionUtils.ThrowSignFailException(this.ChannelId, "微信查询验签未通过。");
            }
            return response.ToResult();           
        }

        public override ITradeRefundApplyResult RefundApply(IRefundApplyInfo apply)
        {
            if (apply == null)
            {
                throw new ArgumentNullException(nameof(apply));
            }
            RefundRequest req = new RefundRequest(apply, channelConfigure);
            return req.Build(this, channelConfigure);
        }

        private static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
        {
            if (errors == SslPolicyErrors.None)
            {
                return true;
            }
            return false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="apply"></param>
        public void TransfersApplyValidate(ITransfersApplyInfo apply)
        {
            if (apply == null)
            {
                TradeChannelExceptionUtils.ThrowChannelValidationException(this, "apply 为 null");
            }
            if (string.IsNullOrWhiteSpace(apply.TransfersNo))
            {
                TradeChannelExceptionUtils.ThrowChannelValidationException(this, "transfersNo 为空或空白值。");
            }
            if (string.IsNullOrWhiteSpace(apply.AccountNo))
            {
                TradeChannelExceptionUtils.ThrowChannelValidationException(this, "accountNo 为空或空白值。");
            }
            //if (string.IsNullOrWhiteSpace(apply.AccountName))
            //{
            //    TradeChannelExceptionUtils.ThrowChannelValidationException(this, "accountName 为空或空白值。");
            //}
            if (apply.TransfersMoney < 1m)
            {
                TradeChannelExceptionUtils.ThrowChannelValidationException(this, "到少需要转账1元。");
            }
            if (string.IsNullOrWhiteSpace(apply.Summary))
            {
                TradeChannelExceptionUtils.ThrowChannelValidationException(this, "summary 为空或空白值。");
            }
            if (string.IsNullOrWhiteSpace(apply.ServerIp))
            {
                TradeChannelExceptionUtils.ThrowChannelValidationException(this, "serverIp 为空或空白值。");
            }
        }

        /// <summary>
        /// 转账申请
        /// </summary>
        /// <param name="apply">申请</param>
        /// <returns></returns>
        public ITransfersApplyResult TransfersApply(ITransfersApplyInfo apply)
        {
            TransfersApplyValidate(apply);
            TransfersRequest req = new TransfersRequest(apply, channelConfigure);
            return req.Build(this, channelConfigure);

            //return new TransfersApplyResult()
            //{
            //    ChannelId = this.ChannelId,
            //    ChannelName = this.ChannelName,
            //    ResultState = TradeApplyResultState.Complete_Success,
            //    ResultStateMessage = "成功",
            //    TradeNo = Guid.NewGuid().ToString("N"),
            //    TransfersFee = 0,
            //    TransfersMoney = apply.TransfersMoney,
            //    TransfersNo = apply.TransfersNo,
            //    TransfersTime = DateTime.Now
            //};
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sercice"></param>
        /// <param name="message"></param>
        public void TransfersNotify(ITransfersNotifyService sercice, object message)
        {
            throw new NotImplementedException("微信不支持转账通知");
        }

        private const string notifyResponse_Success = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";

        private const string notifyResponse_Fail = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[ERROR]]></return_msg></xml>";


        public sealed override string PayNotifyResponse(bool isSuccess)
        {
            if (isSuccess)
            {
                return notifyResponse_Success;
            }
            return notifyResponse_Fail;
        }

        public sealed override string RefundNotifyResponse(bool isSuccess)
        {
            if (isSuccess)
            {
                return notifyResponse_Success;
            }
            return notifyResponse_Fail;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="isSuccess"></param>
        /// <returns></returns>
        public string TransfersNotifyResponse(bool isSuccess)
        {
            if (isSuccess)
            {
                return notifyResponse_Success;
            }
            return notifyResponse_Fail;
        }


    }
}
